package com.ddwl.user.service;

import com.ddwl.common.constant.BaseEnum;
import com.ddwl.common.constant.Constant;
import com.ddwl.common.constant.RedisKey;
import com.ddwl.common.exception.CommonException;
import com.ddwl.common.service.RedisService;
import com.ddwl.schema.bo.user.LoginBo;
import com.ddwl.schema.util.DateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.security.MessageDigest;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @author Fu Zhaohui
 * @version 1.0.0
 * @date 2019/6/28 13:27
 */
@Service
public class TokenService {

    @Autowired
    private RedisService redisService;

    public String getToken(LoginBo bo) {
        BaseEnum.ProductEnum product = BaseEnum.ProductEnum.getProduct(bo.getProduct());
        String userId = bo.getId();
        String timestamp = DateUtil.getCurrDate(DateUtil.DATE_TIME_FORMAT);
        String authKey = RedisKey.TOKEN_KEY.getKey(product.getName(), userId);
        // 保持一个用户只能登录一个设备
        Map<String, String> authMap = redisService.getHashOps().entries(authKey);
        if (!CollectionUtils.isEmpty(authMap)) {
            String ak = authMap.get("ak");
            redisService.getHashOps().getOperations().delete(RedisKey.AUTH_KEY.getKey(product.getName(), ak));
            redisService.getHashOps().getOperations().delete(authKey);
        }
        String ak = this.getAccessToken();
        Map<String, String> tokenMap = new HashMap<>(10);
        tokenMap.put("uid", userId);
        String realname = bo.getRealname();
        if (StringUtils.hasText(realname)) {
            tokenMap.put("realname", realname);
        }
        tokenMap.put("dk", bo.getDk());
        if (StringUtils.hasText(bo.getMobile())) {
            tokenMap.put("mobile", bo.getMobile());
        }
        if (StringUtils.hasText(bo.getUsername())) {
            tokenMap.put("userName", bo.getUsername());
        }
        tokenMap.put("timestamp", timestamp);
        tokenMap.put("userAgent", bo.getUserAgent());
        tokenMap.put("nickname", bo.getNickname());
        tokenMap.put("channel", bo.getChannel());
        tokenMap.put("shopName", bo.getShopName());
        tokenMap.put("shopId", bo.getShopId());
        String tokenKey = RedisKey.AUTH_KEY.getKey(product.getName(), ak);
        redisService.getHashOps().putAll(tokenKey, tokenMap);
        authMap = new HashMap<>(5);
        authMap.put("ak", ak);
        authMap.put("dk", bo.getDk());
        authMap.put("pk", product.getName());
        authMap.put("timestamp", timestamp);
        authMap.put("nickname", bo.getNickname());
        authMap.put("channel", bo.getChannel());
        authMap.put("shopName", bo.getShopName());
        authMap.put("shopId", bo.getShopId());
        if (StringUtils.hasText(bo.getMobile())) {
            authMap.put("mobile", bo.getMobile());
        }
        if (StringUtils.hasText(bo.getUsername())) {
            authMap.put("userName", bo.getUsername());
        }
        redisService.getHashOps().putAll(authKey, authMap);
        if (product.getApp()) {
            redisService.getHashOps().getOperations().expire(tokenKey, Constant.ACCESS_TOKEN_EXPIRE, TimeUnit.DAYS);
            redisService.getHashOps().getOperations().expire(authKey, Constant.ACCESS_TOKEN_EXPIRE, TimeUnit.DAYS);
        } else {
            Calendar calendar = Calendar.getInstance();
            calendar.add(Calendar.DAY_OF_YEAR, 1);
            calendar.set(Calendar.HOUR_OF_DAY, 4);
            calendar.set(Calendar.MINUTE, 0);
            calendar.set(Calendar.SECOND, 0);
            calendar.set(Calendar.MILLISECOND, 0);
            Date dateTime = calendar.getTime();
            redisService.getHashOps().getOperations().expireAt(tokenKey, dateTime);
            redisService.getHashOps().getOperations().expireAt(authKey, dateTime);
        }
        return ak;
    }


    private String getAccessToken() {
        try {
            MessageDigest algorithm = MessageDigest.getInstance("MD5");
            algorithm.reset();
            algorithm.update(UUID.randomUUID().toString().getBytes());
            byte[] messageDigest = algorithm.digest();
            StringBuffer hexString = new StringBuffer();
            for (int i = 0; i < messageDigest.length; i++) {
                hexString.append(Integer.toHexString(0xFF & messageDigest[i]));
            }
            return hexString.toString();
        } catch (Exception e) {
            throw new CommonException("生成Access Token失败", e);
        }
    }
}
